home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / ftw / ftw.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  3KB  |  106 lines

  1. /*
  2. **  FTW
  3. **  Walk a directory hierarchy from a given point, calling a user-supplied
  4. **  function at each thing we find.  If we go below a specified depth,
  5. **  recycle file descriptors.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include "pdftw.h"
  12.  
  13. #ifdef    RCSID
  14. static char RCS[] = "$Header: /proj/wais/wais-8-b2/lib/RCS/ftw.c,v 1.1 91/07/17 16:37:58 jonathan Exp $";
  15. #endif    /* RCSID */
  16.  
  17. #define EQ(a, b)    (strcmp((a), (b)) == 0)
  18.  
  19. extern char        *malloc();
  20. extern char        *strcpy();
  21.  
  22. int
  23. ftw(directory, funcptr, depth)
  24.     char         *directory;
  25.     int            (*funcptr)();
  26.     int              depth;
  27. {
  28.     register DIR     *dirp;
  29.     struct dirent         *entp;
  30.     struct stat          stats;
  31.     register char     *p;
  32.     register int      i;
  33.     long          seekpoint;
  34.     char         *fullpath;
  35.  
  36.     /* If can't stat, tell the user so. */
  37.     if (stat(directory, &stats) < 0)
  38.     return (*funcptr)(directory, &stats, FTW_NS);
  39.  
  40.     /* If it's not a directory, call the user's function. */
  41.     if ((stats.st_mode & S_IFMT) != S_IFDIR)
  42.     /* Saying "FTW_F" here is lying; what if this is a symlink? */
  43.     return (*funcptr)(directory, &stats, FTW_F);
  44.  
  45.     /* Open directory; if we can't, tell the user so. */
  46.     dirp = opendir(directory);
  47.     if (dirp == NULL)
  48.     return (*funcptr)(directory, &stats, FTW_DNR);
  49.  
  50.     /* See if user wants to go further. */
  51.     i = (*funcptr)(directory, &stats, FTW_D);
  52.     if (i) {
  53.     closedir(dirp);
  54.     return i;
  55.     }
  56.  
  57.     /* Get ready to hold the full paths. */
  58.     i = strlen(directory);
  59.     fullpath = malloc(i + 1 + MAXNAMLEN + 1);
  60.     if (fullpath == NULL) {
  61.     closedir(dirp);
  62.     return -1;
  63.     }
  64.     (void)strcpy(fullpath, directory);
  65.     p = &fullpath[i];
  66.     if (i && p[-1] != '/')
  67.     *p++ = '/';
  68.  
  69.     /* Read all entries in the directory.. */
  70.     while (entp = readdir(dirp))
  71.     if (!EQ(entp->d_name, ".") && !EQ(entp->d_name, "..")) {
  72.         if (depth <= 1) {
  73.         /* Going too deep; checkpoint and close this directory. */
  74.         seekpoint = telldir(dirp);
  75.         closedir(dirp);
  76.         dirp = NULL;
  77.         }
  78.  
  79.         /* Process the file. */
  80.         (void)strcpy(p, entp->d_name);
  81.         i = ftw(fullpath, funcptr, depth - 1);
  82.         if (i) {
  83.         /* User's finished; clean up. */
  84.         free(fullpath);
  85.         if (dirp)
  86.             closedir(dirp);
  87.         return i;
  88.         }
  89.  
  90.         /* Reopen the directory if necessary. */
  91.         if (dirp == NULL) {
  92.         dirp = opendir(directory);
  93.         if (dirp == NULL) {
  94.             free(fullpath);
  95.             return -1;
  96.         }
  97.         seekdir(dirp, seekpoint);
  98.         }
  99.     }
  100.  
  101.     /* Clean up. */
  102.     free(fullpath);
  103.     closedir(dirp);
  104.     return 0;
  105. }
  106.